package com.ethink.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ethink.framework.common.constant.CommonRespCode;
import com.ethink.framework.common.db.PageUtils;
import com.ethink.framework.common.exception.BusinessException;
import com.ethink.id.generator.IdGenerator;
import com.ethink.order.api.enums.TocSaleAfterImportLogOrderStatusEnum;
import com.ethink.order.api.enums.TocSaleAfterImportLogOrderTypeEnum;
import com.ethink.order.api.info.TocSaleAfterImportLogDetailInfo;
import com.ethink.order.api.info.TocSaleAfterImportLogInfo;
import com.ethink.order.api.info.TocSaleReturnImportLogDetailInfo;
import com.ethink.order.api.model.SaleOrderMateQtyModel;
import com.ethink.order.api.request.*;
import com.ethink.order.api.response.TocSaleAfterImportLogAddResponse;
import com.ethink.order.api.response.TocSaleAfterImportLogDeleteResponse;
import com.ethink.order.api.response.TocSaleAfterImportLogGetResponse;
import com.ethink.order.api.response.TocSaleAfterImportLogUpdateResponse;
import com.ethink.order.common.entity.TocSaleAfterImportLog;
import com.ethink.order.common.entity.TocSaleAfterImportLogDetail;
import com.ethink.order.common.entity.TocSaleReturnImportLogDetail;
import com.ethink.order.common.mapper.SaleDetailOrderMapper;
import com.ethink.order.common.mapper.TocSaleAfterImportLogDetailMapper;
import com.ethink.order.common.mapper.TocSaleAfterImportLogMapper;
import com.ethink.order.common.mapper.TocSaleReturnImportLogDetailMapper;
import com.ethink.order.converter.TocSaleAfterImportLogConverter;
import com.ethink.order.manager.PublicManager;
import com.ethink.order.manager.SaleChannelRequestManager;
import com.ethink.order.service.TocSaleAfterImportLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * TOC售后导入日志 Service接口实现
 *
 * @author default
 * @date 2023-01-10
 */
@Slf4j
@Service
public class TocSaleAfterImportLogServiceImpl implements TocSaleAfterImportLogService {

    @Autowired
    private TocSaleAfterImportLogMapper tocSaleAfterImportLogMapper;
    @Autowired
    private TocSaleAfterImportLogDetailMapper tocSaleAfterImportLogDetailMapper;
    @Autowired
    private TocSaleReturnImportLogDetailMapper tocSaleReturnImportLogDetailMapper;
    @Autowired
    private TocSaleAfterImportLogConverter tocSaleAfterImportLogConverter;
    @Autowired
    private IdGenerator idGenerator;
    @Autowired
    private SaleDetailOrderMapper saleDetailOrderMapper;

    @Override
    public Page<TocSaleAfterImportLogInfo> queryTocSaleAfterImportLog(TocSaleAfterImportLogQueryRequest request) {
        SaleChannelRequestManager.fill(request, 0, 1, 2);
        return tocSaleAfterImportLogMapper.queryTocSaleAfterImportLog(PageUtils.buildPage(request), request);
    }

    @Override
    public TocSaleAfterImportLogGetResponse getTocSaleAfterImportLogById(Long id) {
        TocSaleAfterImportLogGetResponse response = new TocSaleAfterImportLogGetResponse();
        TocSaleAfterImportLog tocSaleAfterImportLog = tocSaleAfterImportLogMapper.selectById(id);
        if (ObjectUtil.isEmpty(tocSaleAfterImportLog)) {
            return response;
        }
        TocSaleAfterImportLogInfo tocSaleAfterImportLogInfo = BeanUtil.copyProperties(tocSaleAfterImportLog, TocSaleAfterImportLogInfo.class);
        response.setMain(tocSaleAfterImportLogInfo);
        List<TocSaleAfterImportLogDetailInfo> item = tocSaleAfterImportLogDetailMapper.selectDetailByLogId(id);
        response.setItem(item);
        return response;
    }

    @Override
    public List<TocSaleAfterImportLogInfo> listTocSaleAfterImportLog(TocSaleAfterImportLogQueryRequest request) {
        return tocSaleAfterImportLogMapper.listTocSaleAfterImportLog(request);
    }

    @Override
    public TocSaleAfterImportLogAddResponse addTocSaleAfterImportLog(TocSaleAfterImportLogAddRequest request) {
        // 校验没有重复单号
        List<String> shopOrderNoList = request.getItems().stream()
                .map(TocSaleAfterImportLogAddItemRequest::getShopOrderNo)
                .distinct()
                .collect(Collectors.toList());
        // 校验没有重复导入
        List<TocSaleAfterImportLogDetailInfo> ctExistList = tocSaleAfterImportLogDetailMapper
                .selectListByChannelAndShopNo(request.getSaleSubChannel(), shopOrderNoList);
        if (ctExistList.size() > 0) {
            String ctOrderNos = ctExistList.stream().map(TocSaleAfterImportLogDetailInfo::getShopOrderNo).distinct()
                    .collect(Collectors.joining());
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "部分售后单已导入," + ctOrderNos);
        }
        // 校验导入的网店单号在toc退明细表中
        List<TocSaleReturnImportLogDetailInfo> ctReturnExistList = tocSaleReturnImportLogDetailMapper
                .selectListByChannelAndShopNo(request.getSaleSubChannel(), shopOrderNoList);
        if (CollectionUtils.isEmpty(ctReturnExistList)) {
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "导入的售后单都没有退货记录");
        }
        List<String> returnShopOrderNos = ctReturnExistList.stream().map(TocSaleReturnImportLogDetailInfo::getShopOrderNo).distinct()
                .collect(Collectors.toList());
        List<String> result = CollUtil.subtractToList(shopOrderNoList, returnShopOrderNos);
        if (CollUtil.isNotEmpty(result)) {
            String diffStrOrderNos = result.stream().collect(Collectors.joining());
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "部分售后单没退货记录," + diffStrOrderNos);
        }
        //退办公室需校验退货数量不能大于销售单的数量
        if (TocSaleAfterImportLogOrderTypeEnum.T2.eq(request.getOrderType())) {
            List<SaleOrderMateQtyModel> qtyModels = saleDetailOrderMapper.selectMateNumByChannelShopOrderNo(request.getSaleSubChannel(), request.getItems());
            Map<String, SaleOrderMateQtyModel> qtyModelMap = qtyModels.stream().collect(Collectors.toMap(a -> {
                return a.getShopOrderNo() + a.getMateSku();
            }, Function.identity()));
            List<String> filterMateSku = request.getItems().stream().filter(a -> {
                return a.getReturnQty() > qtyModelMap.get(a.getShopOrderNo().trim() + a.getMateSku().trim()).getQty();
            }).map(TocSaleAfterImportLogAddItemRequest::getShopOrderNo).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(filterMateSku)) {
                throw new BusinessException(CommonRespCode.PARAM_ERR.getCode(),
                        String.format("以下网店订单的退货数量超出销售数量:%s", JSON.toJSONString(filterMateSku)));
            }
        }
        TocSaleAfterImportLogAddResponse response = new TocSaleAfterImportLogAddResponse();
        TocSaleAfterImportLog tocSaleAfterImportLog = new TocSaleAfterImportLog();
        BeanUtils.copyProperties(request, tocSaleAfterImportLog);
        String orderNo = idGenerator.sh();
        tocSaleAfterImportLog.setOrderNo(orderNo);
        tocSaleAfterImportLogMapper.insert(tocSaleAfterImportLog);
        for (TocSaleAfterImportLogAddItemRequest item : request.getItems()) {
            TocSaleAfterImportLogDetail detail = new TocSaleAfterImportLogDetail();
            BeanUtil.copyProperties(item, detail, "returnDate");
            detail.setLogId(tocSaleAfterImportLog.getId());
            detail.setReturnDate(DateUtil.parseDate(item.getReturnDate()));
            tocSaleAfterImportLogDetailMapper.insert(detail);
        }
        return response;
    }

    @Override
    public TocSaleAfterImportLogUpdateResponse updateTocSaleAfterImportLog(TocSaleAfterImportLogUpdateRequest request) {
        TocSaleAfterImportLogUpdateResponse response = new TocSaleAfterImportLogUpdateResponse();
        LambdaUpdateWrapper<TocSaleAfterImportLog> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TocSaleAfterImportLog::getId, request.getId());
        // FIXME 按实际业务需求set
        updateWrapper.set(TocSaleAfterImportLog::getOrderStatus, request.getOrderStatus());
        updateWrapper.set(TocSaleAfterImportLog::getCreateUserCode, request.getCreateUserCode());
        updateWrapper.set(TocSaleAfterImportLog::getCreateUserName, request.getCreateUserName());
        tocSaleAfterImportLogMapper.update(null, updateWrapper);
        return response;
    }

    @Override
    public TocSaleAfterImportLogDeleteResponse deleteTocSaleAfterImportLog(Long tocSaleAfterImportLogId) {
        TocSaleAfterImportLogDeleteResponse response = new TocSaleAfterImportLogDeleteResponse();
        TocSaleAfterImportLog tocSaleAfterImportLog = tocSaleAfterImportLogMapper.selectById(tocSaleAfterImportLogId);
        if (!TocSaleAfterImportLogOrderStatusEnum.S1.eq(tocSaleAfterImportLog.getOrderStatus())) {
            throw new BusinessException(CommonRespCode.PARAM_ERR, "仅支持草稿状态下删除");
        }
        LambdaUpdateWrapper<TocSaleAfterImportLog> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TocSaleAfterImportLog::getId, tocSaleAfterImportLogId);
        updateWrapper.set(TocSaleAfterImportLog::getIsDeleted, true);
        tocSaleAfterImportLogMapper.update(null, updateWrapper);
        LambdaUpdateWrapper<TocSaleAfterImportLogDetail> detailWrapper = new LambdaUpdateWrapper<>();
        detailWrapper.eq(TocSaleAfterImportLogDetail::getLogId, tocSaleAfterImportLogId);
        detailWrapper.set(TocSaleAfterImportLogDetail::getIsDeleted, true);
        tocSaleAfterImportLogDetailMapper.update(null, detailWrapper);
        return response;
    }

    @Override
    public List<TocSaleAfterImportLogDetailInfo> queryDetailListByLogId(Long id) {
        return tocSaleAfterImportLogDetailMapper.selectDetailByLogId(id);
    }

    @Override
    public void updateStatus(UpdateStatusBaseRequest updateStatusBaseRequest) {
        tocSaleAfterImportLogMapper.update(null, new LambdaUpdateWrapper<TocSaleAfterImportLog>()
                .eq(TocSaleAfterImportLog::getId, updateStatusBaseRequest.getId())
                .set(TocSaleAfterImportLog::getOrderStatus, updateStatusBaseRequest.getOrderStatus()));
    }

}
